package com.dony.statistic.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dony.common.core.domain.entity.SysDept;
import com.dony.common.utils.SecurityUtils;
import com.dony.common.utils.price.ExchangeRateUtils;
import com.dony.order.domain.Order;
import com.dony.shop.service.IShopeeMerchantService;
import com.dony.statistic.domain.OrderDailySale;
import com.dony.statistic.domain.OrderMonthSale;
import com.dony.statistic.domain.vo.PanelGroupData;
import com.dony.order.service.IOrderService;
import com.dony.statistic.domain.vo.PieChartVo;
import com.dony.statistic.service.IOrderDailySaleService;
import com.dony.statistic.service.IOrderMonthSaleService;
import com.dony.statistic.service.IStatisticService;
import com.dony.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 订单Service业务层处理
 *
 * @author dony
 * @date 2022-09-07
 */
@Slf4j
@Service("statisticService")
public class StatisticServiceImpl implements IStatisticService {


    @Resource
    IOrderService orderService;
    @Resource
    IOrderDailySaleService dailySaleService;
    @Resource
    IOrderMonthSaleService monthSaleService;
    @Resource
    IShopeeMerchantService merchantService;
    @Resource
    ISysDeptService deptService;
    @Resource
    private ExchangeRateUtils rateUtils;
    @Resource
    ThreadPoolTaskExecutor executor;


    @Override
    public List<OrderDailySale> getDailySaleData() {
        QueryWrapper<OrderDailySale> wrapper = new QueryWrapper<>();
        wrapper.between("date", LocalDate.now().minusDays(31), LocalDate.now());
        wrapper.eq("tenant_id", SecurityUtils.getDeptId());
        wrapper.orderByAsc("date");
        return dailySaleService.list(wrapper);
    }

    @Override
    public List<OrderMonthSale> getMonthSaleData() {
        QueryWrapper<OrderMonthSale> wrapper = new QueryWrapper<>();
        wrapper.between("month", LocalDate.now().minusMonths(12), LocalDate.now().withDayOfMonth(1).minusMonths(1));
        wrapper.eq("tenant_id", SecurityUtils.getDeptId());
        wrapper.orderByAsc("month");
        return monthSaleService.list(wrapper);
    }


    @Override
    public PanelGroupData getIndexPanelGroupData() {
        PanelGroupData panelGroupData = new PanelGroupData();
        //获取当前未打包的数据
        QueryWrapper<Order> toDoWrapper = new QueryWrapper<Order>();
        toDoWrapper.eq("sys_status", 1);
        toDoWrapper.eq("tenant_id", SecurityUtils.getDeptId());
        panelGroupData.setToHandle(orderService.count(toDoWrapper));
        //获取紧急的数据
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
//        wrapper.gt("ship_by_date", LocalDateTime.now().plus(-30, ChronoUnit.DAYS));
//        wrapper.lt("ship_by_date", LocalDateTime.now().plus(1, ChronoUnit.DAYS));
        wrapper.in("order_status", "IN_CANCEL","TO_RETURN");
        wrapper.eq("tenant_id", SecurityUtils.getDeptId());
        panelGroupData.setEmergency(orderService.count(wrapper));
        //获取今日订单数
        QueryWrapper<Order> todayWrapper = new QueryWrapper<>();
        todayWrapper.select("order_sn", "income", "total_amount", "currency")
                .ge("create_time", DateUtil.beginOfDay(new Date()))
                .lt("create_time", new Date())
                .notIn("order_status", "UNPAID", "IN_CANCEL", "CANCELLED", "TO_RETURN");
        todayWrapper.eq("tenant_id", SecurityUtils.getDeptId());
        List<Order> todayOrders = orderService.list(todayWrapper);
        panelGroupData.setOrderAmount((long) todayOrders.size());
        panelGroupData.setSalesAmount(getTotalSalesAmount(todayOrders));
        return panelGroupData;
    }

    @Override
    public List<PieChartVo> getMerchantSaleData() {
        List<PieChartVo> ret = new ArrayList<>();
        QueryWrapper<Order> todayWrapper = new QueryWrapper<>();
        todayWrapper.select("merchant_id", "COUNT(order_sn) AS daysToShip");
        todayWrapper.groupBy("merchant_id");
        todayWrapper.ge("create_time", DateUtil.beginOfDay(new Date()))
                .lt("create_time", new Date())
                .notIn("order_status", "UNPAID", "IN_CANCEL", "CANCELLED", "TO_RETURN");
        todayWrapper.eq("tenant_id", SecurityUtils.getDeptId());
        List<Order> todayOrders = orderService.list(todayWrapper);
        for (Order order : todayOrders) {
            if (order.getMerchantId() == null) {
                // 如果 merchantId 为空，单独计算一行
                ret.add(new PieChartVo("独立站", order.getDaysToShip()));
            } else {
                ret.add(new PieChartVo(merchantService.getByMerchantId(order.getMerchantId()).getMerchantName(), order.getDaysToShip()));
            }
        }
        return ret;
    }

    /**
     * 获取今日销量
     */
    private float getTotalSalesAmount(List<Order> todayOrders) {
        //获取今日销量
        float totalSalesAmount = 0f;
        for (Order order : todayOrders) {
            if (order == null) continue;
            //计算人民币价格
            if (order.getIncome() != null) {
                totalSalesAmount += rateUtils.getRMBPriceFloat(order.getCurrency(), order.getIncome());
            } else if (order.getTotalAmount() != null) {
                totalSalesAmount += rateUtils.getRMBPriceFloat(order.getCurrency(), order.getTotalAmount());
            } else {
                log.error("订单总价异常无收入！订单号：{}", order.getOrderSn());
            }
        }
        return totalSalesAmount;
    }


    public Boolean syncDailySaleData() {
        //获取所有的租户
        SysDept dept = new SysDept();
        dept.setParentId(100l);
        List<SysDept> tenants = deptService.selectDeptList(dept);
        tenants.forEach(tenant -> {
            executor.execute(() -> {
                //同步最近一个周的数据
                dailySaleService.syncDailyOrderData(tenant.getDeptId());
                //同步最近一年的数据
                monthSaleService.syncMonthOrderData(tenant.getDeptId());
            });
        });
        return true;
    }


}
